﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization;
using System.Xml;

namespace geoqualMenuBar
{
    internal class Utils
    {
        internal static XmlDocument CreateXmlDoc(MenuBars menu)
        {
            XmlDocument doc = new XmlDocument();

            //(1) the xml declaration is recommended, but not mandatory
            XmlDeclaration xmlDeclaration = doc.CreateXmlDeclaration("1.0", null, null);
            XmlElement root = doc.DocumentElement;
            doc.InsertBefore(xmlDeclaration, root);

            //(2) string.Empty makes cleaner code
            XmlElement element1 = doc.CreateElement(string.Empty, "gqNavMenu", string.Empty);
            doc.AppendChild(element1);

            CreateElements(doc, element1, menu.RootMenu);
            return doc;
        }

        private static void CreateElements(XmlDocument doc, XmlElement el, MenuBars menus)
        {
            if (menus != null) {
                foreach (MenuBarItem menu in menus) {
                    XmlElement element1 = doc.CreateElement(string.Empty, menu.ID, string.Empty);
                    if (!string.IsNullOrEmpty(menu.Tooltip)) {
                        element1.SetAttribute("tooltip", menu.Tooltip);
                    }
                    if (menu.Width.Value > 0) {
                        element1.SetAttribute("width", menu.Width.Value.ToString());
                    }
                    if (menu.Icon != null) {
                        element1.SetAttribute("icon", menu.Icon.ImageUrl);
                    } else if (!string.IsNullOrEmpty(menu.IconUrl)) {
                        element1.SetAttribute("icon", menu.IconUrl);
                    }

                    element1.InnerText = menu.Text;
                    el.AppendChild(element1);
                    if (menu.MenuBarItems != null && menu.MenuBarItems.Count > 0) {
                        CreateElements(doc, element1, menu.MenuBarItems);
                    }
                }
            }
        }

        internal static string SerializeToStream(object input)
        {
            string result = string.Empty;
            try {
                XmlSerializer ser = new XmlSerializer(input.GetType(), "http://schemas.yournamespace.com");
                using (MemoryStream memStm = new MemoryStream()) {
                    ser.Serialize(memStm, input);

                    memStm.Position = 0;
                    result = new StreamReader(memStm).ReadToEnd();
                }
            } catch (StackOverflowException e) {
                string err = e.Message;
            }
            return result;
        }

        internal static object DeserializeFromStream(MemoryStream stream)
        {
            IFormatter formatter = new BinaryFormatter();
            stream.Seek(0, SeekOrigin.Begin);
            object o = formatter.Deserialize(stream);
            return o;
        }

        internal static bool IsSubMenuNode(XmlNode node, XmlNode parentNode)
        {
            if (!node.Equals(FirstChildNode(parentNode)) || node.Equals(FirstChildNode(parentNode)))
                return true;
            return false;
        }

        internal static XmlNode FirstChildNode(XmlNode node)
        {
            if (node.HasChildNodes) {
                foreach (XmlNode subnode in node.ChildNodes) {
                    if (subnode.NodeType != XmlNodeType.Text)
                        return subnode;
                }
            }
            return node;
        }

        internal static bool HasSubMenu(XmlNode node)
        {
            if (node.HasChildNodes) {
                foreach (XmlNode subnode in node.ChildNodes) {
                    if (subnode.NodeType != XmlNodeType.Text)
                        return true;
                }
            }
            return false;
        }

        internal static string GetInnerValue(XmlNode node)
        {
            if (node.HasChildNodes)
                foreach (XmlNode subnode in node.ChildNodes) {
                    if (subnode.NodeType == XmlNodeType.Text)
                        return subnode.InnerText.Trim();
                }
            return node.Name.Replace("_", " ");
        }

        internal static string GetValue(XmlNode node)
        {
            if (node.HasChildNodes)
                foreach (XmlNode subnode in node.ChildNodes) {
                    if (subnode.NodeType != XmlNodeType.Text)
                        return GetNodeValue(subnode);
                }
            return GetNodeValue(node);
        }

        internal static string GetNodeValue(XmlNode node)
        {
            if (node.HasChildNodes) {
                return FirstChildNode(node).ChildNodes[0].InnerText;
            }
            if (node.Attributes.Count > 0) {
                return FirstChildNode(node).Attributes[0].Value;
            }
            return node.Name;
        }
    }
}
